export class Transform {
  m: Array<number>;
  constructor(m = [1, 0, 0, 1, 0, 0]) {
    this.m = (m && m.slice()) || [1, 0, 0, 1, 0, 0];
  }

  copy() {
    return new Transform(this.m);
  }

  point(point) {
    // console.log("point", point)
    const m = this.m;
    const { left, top } = point;
    return {
      left: m[0] * left + m[2] * top + m[4],
      top: m[1] * left + m[3] * top + m[5],
    };
  }
  // 位移
  translate(left: number, top: number) {
    this.m[4] += this.m[0] * left + this.m[2] * top;
    this.m[5] += this.m[1] * left + this.m[3] * top;
    return this;
  }

  // 缩放
  scale(sx: number, sy: number) {
    this.m[0] *= sx;
    this.m[1] *= sx;
    this.m[2] *= sy;
    this.m[3] *= sy;
    return this;
  }

  // 旋转
  rotate(radian: number) {
    const cos = Math.cos(radian);
    const sin = Math.sin(radian);
    const m11 = this.m[0] * cos + this.m[2] * sin;
    const m12 = this.m[1] * cos + this.m[3] * sin;
    const m21 = this.m[0] * -sin + this.m[2] * cos;
    const m22 = this.m[1] * -sin + this.m[3] * cos;

    this.m[0] = m11;
    this.m[1] = m12;
    this.m[2] = m21;
    this.m[3] = m22;
    return this;
  }
  // 获取偏移值
  getTranslation() {
    return {
      left: this.m[4],
      top: this.m[5],
    };
  }

  // 倾斜
  skew(sx: number, sy: number) {
    const m11 = this.m[0] + this.m[2] * sy;
    const m12 = this.m[1] + this.m[3] * sy;
    const m21 = this.m[2] + this.m[0] * sx;
    const m22 = this.m[3] + this.m[1] * sx;
    this.m[0] = m11;
    this.m[1] = m12;
    this.m[2] = m21;
    this.m[3] = m22;
    return this;
  }

  multiply(matrix: Transform) {
    const m11 = this.m[0] * matrix.m[0] + this.m[2] * matrix.m[1];
    const m12 = this.m[1] * matrix.m[0] + this.m[3] * matrix.m[1];

    const m21 = this.m[0] * matrix.m[2] + this.m[2] * matrix.m[3];
    const m22 = this.m[1] * matrix.m[2] + this.m[3] * matrix.m[3];

    const dx = this.m[0] * matrix.m[4] + this.m[2] * matrix.m[5] + this.m[4];
    const dy = this.m[1] * matrix.m[4] + this.m[3] * matrix.m[5] + this.m[5];

    this.m[0] = m11;
    this.m[1] = m12;
    this.m[2] = m21;
    this.m[3] = m22;
    this.m[4] = dx;
    this.m[5] = dy;
    return this;
  }

  invert() {
    const d = 1 / (this.m[0] * this.m[3] - this.m[1] * this.m[2]);
    const m0 = this.m[3] * d;
    const m1 = -this.m[1] * d;
    const m2 = -this.m[2] * d;
    const m3 = this.m[0] * d;
    const m4 = d * (this.m[2] * this.m[5] - this.m[3] * this.m[4]);
    const m5 = d * (this.m[1] * this.m[4] - this.m[0] * this.m[5]);
    this.m[0] = m0;
    this.m[1] = m1;
    this.m[2] = m2;
    this.m[3] = m3;
    this.m[4] = m4;
    this.m[5] = m5;
    return this;
  }

  getMatrix() {
    return this.m;
  }

  setAbsolutePosition(x: number, y: number) {
    const m0 = this.m[0];
    const m1 = this.m[1];
    const m2 = this.m[2];
    const m3 = this.m[3];
    const m4 = this.m[4];
    const m5 = this.m[5];
    const top = (m0 * (y - m5) - m1 * (x - m4)) / (m0 * m3 - m1 * m2);
    const left = (x - m4 - m2 * top) / m0;

    return this.translate(left, top);
  }
}
